package frame.networks.viewers.viewer;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import model.components.links.link.Link;
import model.components.links.link.SdnLink;
import model.components.links.link.VirtualLink;
import model.components.networks.sdn.SdnNetwork;
import model.components.networks.virtual.VirtualNetwork;
import model.components.nodes.node.Node;
import model.components.nodes.node.sdn.SdnNode;
import model.components.nodes.node.sdn.SdnRouter;
import model.components.nodes.node.sdn.SdnServer;
import model.components.nodes.node.sdn.SdnSwitch;
import model.components.nodes.node.virtual.VirtualMachine;
import model.components.nodes.node.virtual.VirtualNode;
import model.components.nodes.node.virtual.VirtualRouter;
import model.components.nodes.node.virtual.VirtualSwitch;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin;
import frame.SimulatorFrame;

public class NetworkPopupGraphMousePlugin extends AbstractPopupGraphMousePlugin implements ActionListener
{
	private Node node;
	public Node getNode(){ return node; }
	public void setNode( Node node ){ this.node = node; }
	
	private JPopupMenu nodePopupMenu;
	public JPopupMenu getNodePopupMenu(){ return nodePopupMenu; }
	public void setNodePopupMenu( JPopupMenu nodePopupMenu ){ this.nodePopupMenu = nodePopupMenu; }
	
	private Link link;
	public Link getLink(){ return link; }
	public void setLink( Link link ){ this.link = link; }
	
	private JPopupMenu linkPopupMenu;
    public JPopupMenu getLinkPopupMenu(){ return linkPopupMenu; }
	public void setLinkPopupMenu( JPopupMenu linkPopupMenu ){ this.linkPopupMenu = linkPopupMenu; }
	
	private SimulatorFrame simulatorFrame;
	public SimulatorFrame getFrame(){ return simulatorFrame; }
	public void setFrame( SimulatorFrame simulatorFrame ){ this.simulatorFrame = simulatorFrame; }
	
	public NetworkPopupGraphMousePlugin( SimulatorFrame simulatorFrame )
    {
    	super( InputEvent.BUTTON3_MASK );
    	
    	this.setFrame( simulatorFrame );
    	
    	this.setNodePopupMenu( new JPopupMenu() );
    	this.setLinkPopupMenu( new JPopupMenu() );
    }
	
	@Override@SuppressWarnings("unchecked")
	protected void handlePopup( MouseEvent mouseEvent )
	{
		VisualizationViewer< Node, Link > visualizationViewer = ( VisualizationViewer< Node, Link > )mouseEvent.getSource();
    
		Node node = visualizationViewer.getPickSupport().getVertex( visualizationViewer.getGraphLayout(), mouseEvent.getPoint().getX(), mouseEvent.getPoint().getY() );
		this.setNode( node );
		
		Link link = visualizationViewer.getPickSupport().getEdge( visualizationViewer.getGraphLayout(), mouseEvent.getPoint().getX(), mouseEvent.getPoint().getY() );
		this.setLink( link );
		
		if( node != null )
		{
			this.updateNodePopupMenu( node );
			this.getNodePopupMenu().show( visualizationViewer, mouseEvent.getX(), mouseEvent.getY() );
		}
		else if( link != null )	
		{
			this.updateLinkPopupMenu( link );
			this.getLinkPopupMenu().show( visualizationViewer, mouseEvent.getX(), mouseEvent.getY() );
		}
	}
	
	private void updateNodePopupMenu( Node node )
	{
    	this.getNodePopupMenu().removeAll();
		this.getNodePopupMenu().add( this.nodeMenuItem( node ) );
	}
	private JMenuItem nodeMenuItem( Node node )
	{
		Icon icon = null;
		
    	if( node.isSelected() )
    		icon = node.getGreenIcon();
    	else
    		icon = node.getGreyIcon();
    	
    	String text = null;
    	
		if( node instanceof SdnRouter || node instanceof VirtualRouter || node instanceof SdnSwitch || node instanceof VirtualSwitch )
			text = "<html><b>" + node.getNetworkName() + ": </b>" + node.getName() + "<br><b>OS: </b>" + node.getOS() + "<br><b>CPU: </b>" + node.getCPU() + " <b>RAM: </b>" + node.getRAM() + "</html>";
		
		else if( node instanceof SdnServer || node instanceof VirtualMachine )
			text = "<html><b>" + node.getNetworkName() + ": </b>" + node.getName() + "<br><b>OS: </b>" + node.getOS() + "<br><b>CPU: </b>" + node.getCPU() + " <b>RAM: </b>" + node.getRAM() + " <b>STORAGE: </b>" + node.getStorage() + "</html>";
		
		JMenuItem nodeMenuItem = new JMenuItem();
		nodeMenuItem.setIcon( icon );
		nodeMenuItem.setText( text );
    	nodeMenuItem.addActionListener( this );
    	
    	return nodeMenuItem;
	}
	
	private void updateLinkPopupMenu( Link link )
	{
		this.getLinkPopupMenu().removeAll();
		this.getLinkPopupMenu().add( this.linkMenuItem( link ) );
	}
	private JMenuItem linkMenuItem( Link link )
	{
    	String iconURL = null;
		String text = "";
    	
		Node firstNode = link.getFirstNode();
    	Node secondNode = link.getSecondNode();
		
    	if( link instanceof SdnLink )
    	{
    		iconURL = "/icons/physicalLink.png";
    		text = "<html><b>" + link.getNetworkName() + ": </b>" + link.getName() + " <b>BW: </b> " + link.getBW() + "<br><b>Endpoints: </b>" + firstNode.getName() + "-" + secondNode.getName() + "<br><b>Distance: </b>" + ( (SdnLink) link ).getDistance() + "</html>";
    	}
    		
    	else if( link instanceof VirtualLink )
    	{
    		iconURL = "/icons/virtualLink.png";
    		text = "<html><b>" + link.getNetworkName() + ": </b>" + link.getName() + " <b>BW: </b> " + link.getBW() + "<br><b>Endpoints: </b>" + firstNode.getName() + "-" + secondNode.getName() + "</html>";
    	}
    	
    	JMenuItem linkMenuItem = new JMenuItem();
    	linkMenuItem.setText( text );
    	linkMenuItem.setIcon( new ImageIcon( this.getClass().getResource( iconURL ) ) );
    	linkMenuItem.addActionListener( this );
    	
    	return linkMenuItem;
	}
	
	@Override
	public void actionPerformed( ActionEvent actionEvent )
	{
		this.setFalseSelectedSdnNetworks();
		this.setFalseSelectedVirtualNetworks();
		
		if( this.getNode() != null )
		{
			this.getNode().setSelected( true );
		}
		else if( this.getLink() != null )
		{
			this.getLink().setSelected( true );
			this.getLink().getFirstNode().setSelected( true );
			this.getLink().getSecondNode().setSelected( true );
		}
		
		this.getFrame().getNetworksPanel().getVirtualNetworksVisualizationViewersTabbedPane().repaint();
		this.getFrame().getNetworksPanel().getSdnNetworksViewersTabbedPane().repaint();
	}
	private void setFalseSelectedSdnNetworks()
	{
		List< SdnNetwork > sdnNetworks = this.getFrame().getSimulator().getSdnNetworks();
		
		for( int i = 0; i < sdnNetworks.size(); i++ )
		{
			SdnNetwork sdnNetwork = sdnNetworks.get( i );
			
			for( SdnNode sdnNode: sdnNetwork.getSdnNodes() )
				sdnNode.setSelected( false );
			
			for( SdnLink sdnLink: sdnNetwork.getSdnLinks() )
				sdnLink.setSelected( false );
		}
	}
	private void setFalseSelectedVirtualNetworks()
	{
		List< VirtualNetwork > virtualNetworks = this.getFrame().getSimulator().getVirtualNetworks();
		
		for( int i = 0; i < virtualNetworks.size(); i++ )
		{
			VirtualNetwork virtualNetwork = virtualNetworks.get( i );
			
			for( VirtualNode virtualNode: virtualNetwork.getVirtualNodes() )
				virtualNode.setSelected( false );
			
			for( VirtualLink virtualLink: virtualNetwork.getVirtualLinks() )
				virtualLink.setSelected( false );
		}
	}
	
}
